#pragma once
#include "cfg.h"
#include <map>
#include <vector> 
#include <bitset>

namespace live_var
{
    const int MAX_VAR_CNT = 1024;

    struct InstrLiveness
    {
        std::bitset<MAX_VAR_CNT> use;
        std::bitset<MAX_VAR_CNT> def;
        std::bitset<MAX_VAR_CNT> in;
        std::bitset<MAX_VAR_CNT> out;
    };

    struct BlockLiveness
    {
        std::bitset<MAX_VAR_CNT> use;
        std::bitset<MAX_VAR_CNT> def;
        std::bitset<MAX_VAR_CNT> in;
        std::bitset<MAX_VAR_CNT> out;
        std::vector<InstrLiveness> instrs_liveness;
    };

    struct FuncLiveness
    {
        // block_liveness_map[block_label] = block_liveness
        // var_index_map[var_name] = var_index
        std::map<std::string, BlockLiveness> block_liveness_map;
        std::map<std::string, int> var_index_map; 
    };

    class LiveVarAnalyzer
    {
    public:
        FuncLiveness Analyze(cfg::CFG& cfg);
    private:
        void BuildVarIndex(cfg::CFG& cfg);
        void ComputeInstrUseDef(cfg::CFG& cfg);
        void ComputeBlockUseDef(cfg::CFG& cfg);
        void ComputeBlockInOut(cfg::CFG& cfg);
        void ComputeInstrInOut(cfg::CFG& cfg);

        FuncLiveness func_liveness;
        std::map<std::string, BlockLiveness> block_liveness_map;
        std::map<std::string, int> var_index_map; 
    };
}